package com.xnyzc.lhy.mis.service.impl.cms.amount;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xnyzc.lhy.common.component.convert.DateToStringConverter;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.EOrderType;
import com.xnyzc.lhy.common.penum.amount.EAmountType;
import com.xnyzc.lhy.common.penum.amount.EAssignType;
import com.xnyzc.lhy.common.penum.cms.amount.EDistributionType;
import com.xnyzc.lhy.common.penum.dept.EOffIceType;
import com.xnyzc.lhy.common.penum.pay.ETransactionOrderNoType;
import com.xnyzc.lhy.common.penum.wallet.EIsTransaction;
import com.xnyzc.lhy.common.penum.wallet.ERecordType;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.common.util.IDUtil;
import com.xnyzc.lhy.common.util.validate.validateMoneyUtil;
import com.xnyzc.lhy.mis.entity.cms.amount.OaSysOfficeAmount;
import com.xnyzc.lhy.mis.entity.cms.amount.OaSysOfficeRecord;
import com.xnyzc.lhy.mis.entity.sidebar.OaCUserOffice;
import com.xnyzc.lhy.mis.entity.sidebar.OaSysOffice;
import com.xnyzc.lhy.mis.entity.system.OaSysUser;
import com.xnyzc.lhy.mis.entity.user.OaCUser;
import com.xnyzc.lhy.mis.entity.user.wallet.OaCWallet;
import com.xnyzc.lhy.mis.entity.user.wallet.OaCWalletRecord;
import com.xnyzc.lhy.mis.entity.util.OrderUtil;
import com.xnyzc.lhy.mis.mapper.cms.amount.OaSysOfficeAmountMapper;
import com.xnyzc.lhy.mis.mapper.cms.amount.OaSysOfficeRecordMapper;
import com.xnyzc.lhy.mis.mapper.sidebar.OaCUserOfficeMapper;
import com.xnyzc.lhy.mis.mapper.sidebar.OaSysOfficeMapper;
import com.xnyzc.lhy.mis.mapper.system.OaSysUserMapper;
import com.xnyzc.lhy.mis.mapper.user.OaCUserMapper;
import com.xnyzc.lhy.mis.mapper.user.wallet.OaCWalletMapper;
import com.xnyzc.lhy.mis.mapper.user.wallet.OaCWalletRecordMapper;
import com.xnyzc.lhy.mis.service.cms.amount.IOaSysDistributionAmountService;
import com.xnyzc.lhy.mis.service.cms.util.IOaSysGetOfficeIdListService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @Description 后台分配额度
 * @Author zhuyubin
 * @Date 2019-08-22 14:13
 **/
@Service
public class OaSysDistributionAmountServiceImpl implements IOaSysDistributionAmountService {

    @Autowired
    private OaSysOfficeMapper oaSysOfficeMapper;
    @Autowired
    private OaCUserOfficeMapper oaCUserOfficeMapper;
    @Autowired
    private OaCUserMapper oaCUserMapper;
    @Autowired
    private OaSysOfficeAmountMapper oaSysOfficeAmountMapper;
    @Autowired
    private OaCWalletMapper oaCWalletMapper;
    @Autowired
    private OaSysOfficeRecordMapper oaSysOfficeRecordMapper;
    @Autowired
    private OaCWalletRecordMapper oaCWalletRecordMapper;
    @Autowired
    private OaSysUserMapper oaSysUserMapper;
    @Autowired
    private IOaSysGetOfficeIdListService iOaSysGetOfficeIdListService;

    /**
     * 根据机构id查询出当前节点的子节点
     * @param officeId 机构id
     * @param tag 租户
     * @return
     */
    @Override
    public Map<String, Object> selectOfficeOrUserByOfficeId(Long officeId, String tag, Long current, String name, String phone, Long searchOfficeId){
        Map<String, Object> result = new HashMap<>(16);
        result.put("amountType", EAmountType.officeAmount.getValue());
        result.put("personalAmount", "0");
        result.put("officeAmount", "0");
        List<OaCUserOffice> oaCUserOfficeList = oaCUserOfficeMapper.selectList(
                Wrappers.<OaCUserOffice>lambdaQuery()
                        .eq(OaCUserOffice::getTag, tag)
                        .eq(OaCUserOffice::getOfficeId, officeId));
        // 给机构分
        if (CheckUtil.objIsEmpty(oaCUserOfficeList)){
            result = this.officeMap(tag, officeId, name, current, result, searchOfficeId);
        }
        // 给人分
        else {
            result = this.personal(officeId, tag, phone, name, current, result);
        }
        OaSysOfficeAmount oaSysOfficeAmount = oaSysOfficeAmountMapper.selectOne(
                Wrappers.<OaSysOfficeAmount>lambdaQuery()
                        .eq(OaSysOfficeAmount::getTag, tag)
                        .eq(OaSysOfficeAmount::getOfficeId, officeId)
        );
        if (CheckUtil.objIsNotEmpty(oaSysOfficeAmount)){
            result.put("personalAmount", this.isBigDecimalNull(oaSysOfficeAmount.getPersonalAmount()));
            result.put("officeAmount", this.isBigDecimalNull(oaSysOfficeAmount.getOfficeAmount()));
        }
        return result;
    }

    /**
     * 分配额度
     * @param userId 当前用户id
     * @param officeId 当前部门id
     * @param ids 部门id 或 用户id 数组
     * @param amount 分配额度
     * @param tag 租户
     * @param amountType 分配额度类型
     * @return
     */
    @Override
    public String distributionAmount(Long userId, Long officeId, List<Long> ids, BigDecimal amount, String tag, Integer amountType){
        Date date = new Date();
        BigDecimal zero = new BigDecimal("0");
        // 校验额度
        if (!validateMoneyUtil.validateAmount(amount)){
            throw PangException.create(EErrorCode.notMoney);
        }
        // 查询全部子节点
        List<OaSysOffice> oaSysOffices = oaSysOfficeMapper.selectList(
                Wrappers.<OaSysOffice>lambdaQuery()
                        .eq(OaSysOffice::getTag, tag)
                        .eq(OaSysOffice::getParentId, officeId)
        );
        OaSysOffice oaSysOffice = oaSysOfficeMapper.selectById(officeId);
        // 提额人数
        int size = ids.size();
        // 部门额度关联
        OaSysOfficeAmount oaSysOfficeAmount = oaSysOfficeAmountMapper.selectOne(
                Wrappers.<OaSysOfficeAmount>lambdaQuery()
                        .eq(OaSysOfficeAmount::getTag, tag)
                        .eq(OaSysOfficeAmount::getOfficeId, officeId)
        );
        // 没有分配过额度
        if (CheckUtil.objIsEmpty(oaSysOfficeAmount)){
            throw PangException.create(EErrorCode.undistributionAmount);
        }
        // 需要分配的总额度
        BigDecimal allAmount = amount.multiply(new BigDecimal(String.valueOf(size)));
        // 剩余额度
        BigDecimal lastAmount = this.getLastAmount(amountType, oaSysOfficeAmount, oaSysOffice, size, zero, allAmount);
        // 人员分配
        if (CheckUtil.objIsEmpty(oaSysOffices)){
            this.distributionPersonal(officeId, ids, tag, amountType, EAssignType.assignPersonal.getValue(), amount, userId, date);
        }
        // 部门分配
        else {
            this.distributionOffice(officeId, ids, tag, amountType, EAssignType.assignOffice.getValue(), amount, userId, date, zero);
        }
        // 分配额度类型
        if (EAmountType.personalAmount.getValue().equals(amountType)){
            // 更新当前剩额度
            oaSysOfficeAmount.setPersonalAmount(lastAmount);
        } else {
            // 更新当前剩额度
            oaSysOfficeAmount.setOfficeAmount(lastAmount);
        }
        oaSysOfficeAmount.setUpdateUser(userId);
        oaSysOfficeAmount.setUpdateTime(date);
        int i = oaSysOfficeAmountMapper.updateById(oaSysOfficeAmount);
        if (i != 1){
            throw PangException.create(EErrorCode.distributionAmountFailure);
        }
        return EErrorCode.distributionAmountSuccess.getDesc();
    }

    /**
     * 查询分配额度明细
     * @param userId 用户id
     * @param tag 租户
     * @param officeId 机构id
     * @param amountType 额度类型
     * @param starTime 开始时间
     * @param name 机构名
     * @return
     */
    @Override
    public IPage<Map<String, Object>> selectOfficeRecord(Long userId, String tag, Long officeId, Integer amountType, Long current, List<Date> starTime,  String name, String createName, Long size, Long searchOfficeId){
        // 查询全部子节点
        OaSysOffice oaSysOffice = oaSysOfficeMapper.selectById(officeId);
        if (CheckUtil.objIsEmpty(oaSysOffice)){
            throw PangException.create(EErrorCode.unClickOffice);
        }
        int officeType = oaSysOffice.getType();
        IPage<Map<String, Object>> page = new Page<>();
        LambdaQueryWrapper<OaSysOfficeRecord> qw = Wrappers.<OaSysOfficeRecord>lambdaQuery()
                .eq(OaSysOfficeRecord::getOfficeId, officeId)
                .eq(OaSysOfficeRecord::getTag, tag)
                .eq(OaSysOfficeRecord::getAmountType, amountType)
                .orderByDesc(OaSysOfficeRecord::getCreateTime);
        if (CheckUtil.objIsNotEmpty(createName)){
            qw.like(OaSysOfficeRecord::getCreateName, createName);
        }
        if (CheckUtil.objIsNotEmpty(name)){
            // 是部门显示用户
            if (EOffIceType.dept.getValue().equals(Integer.valueOf(officeType))){
                List<OaCUser> oaCUsers = oaCUserMapper.selectList(Wrappers.<OaCUser>lambdaQuery().eq(OaCUser::getTag, tag).like(OaCUser::getUserName, name));
                List<Long> userIds = new ArrayList<>();
                for (OaCUser oaCUser : oaCUsers) {
                    userIds.add(oaCUser.getUserId());
                }
                qw.in(OaSysOfficeRecord::getAssignUserid, userIds);
            }
        }
        if (CheckUtil.objIsNotEmpty(searchOfficeId)){
            qw.eq(OaSysOfficeRecord::getAssignOffice, searchOfficeId);
        }
        Page<OaSysOfficeRecord> oaSysOfficeRecordPage = new Page<>();
        oaSysOfficeRecordPage.setCurrent(current);
        if (CheckUtil.objIsNotEmpty(size)){
            oaSysOfficeRecordPage.setSize(size);
        } else {
            oaSysOfficeRecordPage.setSize(20L);
        }
        IPage<OaSysOfficeRecord> oaSysOfficeRecordIPage = oaSysOfficeRecordMapper.selectPage(oaSysOfficeRecordPage, qw);
        List<Map<String, Object>> list = new ArrayList<>();
        List<Long> assignUserids = new ArrayList<>();
        List<Long> assignOfficeIds = new ArrayList<>();
        for (OaSysOfficeRecord oaSysOfficeRecord : oaSysOfficeRecordIPage.getRecords()) {
            Map<String, Object> map = new HashMap<>(16);
            // 是部门显示用户
            if (EOffIceType.dept.getValue().equals(Integer.valueOf(officeType))){
                assignUserids.add(oaSysOfficeRecord.getAssignUserid());
                Long assignUserid = oaSysOfficeRecord.getAssignUserid();
                map.put("assignUserId", "");
                if (CheckUtil.objIsNotEmpty(assignUserid)){
                    map.put("assignUserId", assignUserid);
                }
            }
            // 非部门机构
            else {
                assignOfficeIds.add(oaSysOfficeRecord.getAssignOffice());
                Long assignOffice = oaSysOfficeRecord.getAssignOffice();
                map.put("assignOfficeId", "");
                if (CheckUtil.objIsNotEmpty(assignOffice)){
                    map.put("assignOfficeId", assignOffice);
                }
            }
            // 分配类型
            map.put("distributionType", CheckUtil.objIsEmpty(oaSysOfficeRecord.getDistributionType()) ? "" : EDistributionType.findByValue(oaSysOfficeRecord.getDistributionType()).getDesc());
            map.put("name", "");
            map.put("createUserName", oaSysOfficeRecord.getCreateName());
            map.put("createTime", new DateToStringConverter().convert(oaSysOfficeRecord.getCreateTime()));
            map.put("amount", oaSysOfficeRecord.getAmount());
            list.add(map);
        }
        // 用户
        List<OaCUser> oaCUsers = oaCUserMapper.selectList(Wrappers.<OaCUser>lambdaQuery().eq(OaCUser::getTag, tag).in(OaCUser::getUserId, assignUserids));
        // 机构
        List<OaSysOffice> offices = oaSysOfficeMapper.selectList(Wrappers.<OaSysOffice>lambdaQuery().eq(OaSysOffice::getTag, tag).in(OaSysOffice::getOfficeId, assignOfficeIds));
        List<Map<String, Object>> result = new ArrayList<>();
        for (Map<String, Object> map : list) {
            // 是部门显示用户
            if (EOffIceType.dept.getValue().equals(Integer.valueOf(officeType))){
                for (OaCUser oaCUser : oaCUsers) {
                    if (map.get("assignUserId").toString().equals(oaCUser.getUserId().toString())){
                        map.put("name", oaCUser.getUserName());
                    }
                }
            } else {
                for (OaSysOffice office : offices) {
                    if (map.get("assignOfficeId").toString().equals(office.getOfficeId().toString())){
                        map.put("name", office.getName());
                    }
                }
            }
            result.add(map);
        }
        page.setRecords(result);
        page.setCurrent(oaSysOfficeRecordIPage.getCurrent());
        page.setTotal(oaSysOfficeRecordIPage.getTotal());
        page.setPages(oaSysOfficeRecordIPage.getPages());
        page.setSize(oaSysOfficeRecordIPage.getSize());
        return page;
    }

    /**
     * 充值额度
     * @param sysUserId 后台用户id
     * @param tag 租户
     * @param officeId 部门id
     * @param personalAmount 个人额度
     * @param officeAmount 部门额度
     * @return
     */
    @Override
    public String rechargeOfficeAmount(Long sysUserId, String tag, Long officeId, String personalAmount, String officeAmount){
        Date date = new Date();
        BigDecimal zero = new BigDecimal("0");
        String pattern = "^(([1-9][0-9]*)|(([0]\\.\\d{1,2}|[1-9][0-9]*\\.\\d{1,2})))$";
        Pattern p = Pattern.compile(pattern);
        List<OaSysOfficeAmount> oaSysOfficeAmounts = oaSysOfficeAmountMapper.selectList(
                Wrappers.<OaSysOfficeAmount>lambdaQuery()
                        .eq(OaSysOfficeAmount::getTag, tag)
                        .eq(OaSysOfficeAmount::getOfficeId, officeId));
        BigDecimal personalAmountBig;
        BigDecimal officeAmounBig;
        // 额度不空
        if (CheckUtil.objIsNotEmpty(personalAmount) || CheckUtil.objIsNotEmpty(officeAmount)){
            // 关联过修改
            if (oaSysOfficeAmounts.size() == 1){
                // 部门额度关联
                OaSysOfficeAmount oaSysOfficeAmount = oaSysOfficeAmounts.get(0);
                oaSysOfficeAmount.setUpdateTime(date);
                oaSysOfficeAmount.setUpdateUser(sysUserId);
                // 插入分配额度记录
                if (CheckUtil.objIsNotEmpty(personalAmount)){
                    boolean matches = Pattern.matches(p.pattern(), personalAmount);
                    if (!matches){
                        throw PangException.create(EErrorCode.unAmount);
                    }
                    personalAmountBig = new BigDecimal(personalAmount);
                    if (personalAmountBig.compareTo(zero) == -1){
                        throw PangException.create(EErrorCode.notAmountNegative);
                    }
                    // 原本个人的钱
                    BigDecimal amount = oaSysOfficeAmount.getPersonalAmount();
                    if (CheckUtil.objIsEmpty(amount)){
                        amount = zero;
                    }
                    // 加钱
                    oaSysOfficeAmount.setPersonalAmount(amount.add(personalAmountBig));
                }
                if (CheckUtil.objIsNotEmpty(officeAmount)){
                    boolean matches = Pattern.matches(p.pattern(), officeAmount);
                    if (!matches){
                        throw PangException.create(EErrorCode.unAmount);
                    }
                    officeAmounBig = new BigDecimal(officeAmount);
                    if (officeAmounBig.compareTo(zero) == -1){
                        throw PangException.create(EErrorCode.notAmountNegative);
                    }
                    // 原本部门的钱
                    BigDecimal amount = oaSysOfficeAmount.getOfficeAmount();
                    if (CheckUtil.objIsEmpty(amount)){
                        amount = zero;
                    }
                    // 加钱
                    oaSysOfficeAmount.setOfficeAmount(amount.add(officeAmounBig));
                }
                int i = oaSysOfficeAmountMapper.updateById(oaSysOfficeAmount);
                if (i != 1){
                    throw PangException.create(EErrorCode.rechargeFailure);
                }
            }
            // 未关联新增
            else {
                OaSysOfficeAmount oaSysOfficeAmount = new OaSysOfficeAmount();
                oaSysOfficeAmount.setOfficeAmountId(IDUtil.nextId());
                oaSysOfficeAmount.setOfficeId(officeId);
                if (CheckUtil.objIsNotEmpty(personalAmount)){
                    personalAmountBig = new BigDecimal(personalAmount);
                    // 加钱
                    oaSysOfficeAmount.setPersonalAmount(personalAmountBig);
                }
                if (CheckUtil.objIsNotEmpty(officeAmount)){
                    officeAmounBig = new BigDecimal(officeAmount);
                    // 加钱
                    oaSysOfficeAmount.setOfficeAmount(officeAmounBig);
                }
                oaSysOfficeAmount.setTag(tag);
                oaSysOfficeAmount.setCreateUser(sysUserId);
                oaSysOfficeAmount.setCreateTime(date);
                oaSysOfficeAmount.setUpdateUser(sysUserId);
                oaSysOfficeAmount.setUpdateTime(date);
                int i = oaSysOfficeAmountMapper.insert(oaSysOfficeAmount);
                if (i != 1){
                    throw PangException.create(EErrorCode.rechargeFailure);
                }
            }
            // 插入分配额度记录
            if (CheckUtil.objIsNotEmpty(personalAmount)){
                personalAmountBig = new BigDecimal(personalAmount);
                this.rechargeOfficeAmountRecord(officeId, sysUserId, tag, date, personalAmountBig, EAmountType.personalAmount);
            }
            if (CheckUtil.objIsNotEmpty(officeAmount)){
                officeAmounBig = new BigDecimal(officeAmount);
                this.rechargeOfficeAmountRecord(officeId, sysUserId, tag, date, officeAmounBig, EAmountType.officeAmount);
            }
        }
        // 空额度直接打回
        else {
            throw PangException.create(EErrorCode.unAmount);
        }
        return EErrorCode.rechargeSuccess.getDesc();
    }

    /**
     * 分配额度搜索部门树
     * @param sysUserId 后台用户id
     * @param tag 用户来源
     * @param officeId
     * @return
     */
    @Override
    public List<Map<String, Object>> searchOfficeTreeMap(Long sysUserId, String tag, Long officeId){
        // 可查看部门id
        List<Long> officeIds = iOaSysGetOfficeIdListService.selectOfficeIdList(sysUserId);
        List<Map<String, Object>> result = new ArrayList<>();
        Map<String, Object> map = new HashMap<>(16);
        // 当前跟公司
        OaSysOffice oaSysOffice = oaSysOfficeMapper.selectById(officeId);
        if (CheckUtil.objIsEmpty(oaSysOffice)){
            return result;
        }
        map.put("id", oaSysOffice.getOfficeId());
        map.put("pId", oaSysOffice.getParentId());
        map.put("name", oaSysOffice.getName());
        List<OaSysOffice> offices = oaSysOfficeMapper.selectList(
                Wrappers.<OaSysOffice>lambdaQuery()
                        .eq(OaSysOffice::getTag, tag)
                        .eq(OaSysOffice::getParentId, officeId)
                        .eq(OaSysOffice::getType, EOffIceType.dept.getValue())
                        .in(OaSysOffice::getOfficeId, officeIds));
        List<Map<String, Object>> children = new ArrayList<>();
        for (OaSysOffice office : offices) {
            Map<String, Object> childrenMap = new HashMap<>(16);
            childrenMap.put("id", office.getOfficeId());
            childrenMap.put("pId", office.getParentId());
            childrenMap.put("name", office.getName());
            children.add(childrenMap);
        }
        if (CheckUtil.objIsNotEmpty(children)){
            map.put("children", children);
        }
        result.add(map);
        return result;
    }

    /**
     * 插入记录
     * @param officeId
     * @param sysUserId
     * @param tag
     * @param date
     */
    private void rechargeOfficeAmountRecord(Long officeId, Long sysUserId, String tag, Date date, BigDecimal amount, EAmountType eAmountType){
        // 部门收支记录
        OaSysOfficeRecord oaSysOfficeRecord = new OaSysOfficeRecord();
        oaSysOfficeRecord.setOfficeRecordId(IDUtil.nextId());
        oaSysOfficeRecord.setOfficeId(officeId);
        oaSysOfficeRecord.setAssignOffice(officeId);
        oaSysOfficeRecord.setDistributionType(EDistributionType.recharge.getValue());
        OaSysUser oaSysUser = oaSysUserMapper.selectById(sysUserId);
        if (CheckUtil.objIsNotEmpty(oaSysUser)){
            oaSysOfficeRecord.setCreateName(oaSysUser.getName());
        }
        oaSysOfficeRecord.setTag(tag);
        oaSysOfficeRecord.setCreateUser(sysUserId);
        oaSysOfficeRecord.setCreateTime(date);
        oaSysOfficeRecord.setUpdateUser(sysUserId);
        oaSysOfficeRecord.setUpdateTime(date);
        oaSysOfficeRecord.setAmountType(eAmountType.getValue());
        oaSysOfficeRecord.setAmount(amount);
        int i = oaSysOfficeRecordMapper.insert(oaSysOfficeRecord);
        if (i != 1){
            throw PangException.create(EErrorCode.rechargeFailure);
        }
    }

    /**
     * 部门业务
     * @param officeId 机构id
     * @param ids id列表
     * @param tag 租户
     * @param amountType 额度类型
     * @param amount 额度
     * @param userId 用户id
     * @param date 当前时间
     * @param zero 小数0
     * @return
     */
    private void distributionOffice(Long officeId, List<Long> ids, String tag, Integer amountType, Integer assignType, BigDecimal amount, Long userId, Date date, BigDecimal zero){
        int i;
        for (Long id : ids) {
            // 关联表
            OaSysOfficeAmount officeAmount = oaSysOfficeAmountMapper.selectOne(
                    Wrappers.<OaSysOfficeAmount>lambdaQuery()
                            .eq(OaSysOfficeAmount::getTag, tag)
                            .eq(OaSysOfficeAmount::getOfficeId, id)
            );
            // 若没有关联，初始化记录
            if (CheckUtil.objIsEmpty(officeAmount)){
                officeAmount = new OaSysOfficeAmount();
                officeAmount.setOfficeAmountId(IDUtil.nextId());
                officeAmount.setOfficeId(id);
                // 分配额度类型
                if (EAmountType.personalAmount.getValue().equals(amountType)){
                    officeAmount.setPersonalAmount(amount);
                    officeAmount.setOfficeAmount(zero);
                } else {
                    officeAmount.setPersonalAmount(zero);
                    officeAmount.setOfficeAmount(amount);
                }
                officeAmount.setTag(tag);
                officeAmount.setCreateUser(userId);
                officeAmount.setCreateTime(date);
                officeAmount.setUpdateUser(userId);
                officeAmount.setUpdateTime(date);
                i = oaSysOfficeAmountMapper.insert(officeAmount);
                if (i != 1){
                    throw PangException.create(EErrorCode.distributionAmountFailure);
                }
            } else {
                // 分配额度类型
                if (EAmountType.personalAmount.getValue().equals(amountType)){
                    officeAmount.setPersonalAmount(officeAmount.getPersonalAmount().add(amount));
                } else {
                    officeAmount.setOfficeAmount(officeAmount.getOfficeAmount().add(amount));
                }
                officeAmount.setUpdateUser(userId);
                officeAmount.setUpdateTime(date);
                i = oaSysOfficeAmountMapper.updateById(officeAmount);
                if (i != 1){
                    throw PangException.create(EErrorCode.distributionAmountFailure);
                }
            }
            this.insertOaSysOfficeRecord(officeId, amount, amountType, assignType, userId, tag, null, id);
        }
    }

    /**
     * 人员业务
     * @param officeId 机构id
     * @param ids id列表
     * @param tag 租户
     * @param amountType 额度类型
     * @param amount 额度
     * @param userId 用户id
     * @param date 当前时间
     * @return
     */
    private void distributionPersonal(Long officeId, List<Long> ids, String tag, Integer amountType, Integer assignType, BigDecimal amount, Long userId, Date date){
        for (Long id : ids) {
            // 钱包
            OaCWallet oaCWallet = oaCWalletMapper.selectOne(
                    Wrappers.<OaCWallet>lambdaQuery()
                            .eq(OaCWallet::getTag, tag)
                            .eq(OaCWallet::getUserId, id)
            );
            if (CheckUtil.objIsEmpty(oaCWallet)){
                throw PangException.create(EErrorCode.unWallet);
            }
            // 分配额度类型
            if (EAmountType.personalAmount.getValue().equals(amountType)){
                oaCWallet.setPersonalOfficialBalance(oaCWallet.getPersonalOfficialBalance().add(amount));
            } else {
                oaCWallet.setDeptOfficialBalance(oaCWallet.getDeptOfficialBalance().add(amount));
            }
            oaCWallet.setUpdateUser(userId);
            oaCWallet.setUpdateTime(date);
            int i = oaCWalletMapper.updateById(oaCWallet);
            if (i != 1){
                throw PangException.create(EErrorCode.distributionAmountFailure);
            }
            // 分配记录，额度收支明细中
            OaCWalletRecord oaCWalletRecord = new OaCWalletRecord();
            oaCWalletRecord.setRecordId(IDUtil.nextId());
            oaCWalletRecord.setUserId(id);
            oaCWalletRecord.setOrderNo(OrderUtil.orderNo(EOrderType.TEGR));
            oaCWalletRecord.setActualAmount(amount);
            oaCWalletRecord.setWalletBalance(oaCWallet.getWalletBalance());
            oaCWalletRecord.setPersonalOfficialBalance(oaCWallet.getPersonalOfficialBalance());
            oaCWalletRecord.setDeptOfficialBalance(oaCWallet.getDeptOfficialBalance());
            oaCWalletRecord.setRecordType(ERecordType.myTopUp.getType());
            oaCWalletRecord.setIsTransaction(EIsTransaction.paySuccess.getValue());
            oaCWalletRecord.setUpdateUser(userId);
            oaCWalletRecord.setTag(tag);
            oaCWalletRecord.setCreateTime(date);
            oaCWalletRecord.setUpdateTime(date);
            oaCWalletRecord.setCreateUser(userId);
            oaCWalletRecord.setTransactionTime(date);
            // 分配额度类型
            if (EAmountType.personalAmount.getValue().equals(amountType)){
                oaCWalletRecord.setTransactionOrderNo(OrderUtil.transactionOrderNo(ETransactionOrderNoType.personalBusiness));
            } else {
                oaCWalletRecord.setTransactionOrderNo(OrderUtil.transactionOrderNo(ETransactionOrderNoType.deptService));
            }
            i = oaCWalletRecordMapper.insert(oaCWalletRecord);
            if (i != 1){
                throw PangException.create(EErrorCode.distributionAmountFailure);
            }
            this.insertOaSysOfficeRecord(officeId, amount, amountType, assignType, userId, tag, id, null);
        }
    }

    /**
     * 人业务
     * @param officeId 机构id
     * @param tag 租户
     * @param phone 手机号
     * @param name 用户名
     * @param current
     * @param result
     * @return
     */
    private Map<String, Object> personal(Long officeId, String tag, String phone, String name, Long current,  Map<String, Object> result){
        IPage<Map<String, Object>> page = new Page<>();
        result.put("amountType", EAmountType.personalAmount.getValue());
        // 根据机构获取用户id
        List<OaCUserOffice> oaCUserOffices = oaCUserOfficeMapper.selectList(
                Wrappers.<OaCUserOffice>lambdaQuery()
                        .eq(OaCUserOffice::getOfficeId, officeId)
                        .eq(OaCUserOffice::getTag, tag)
        );
        if (CheckUtil.objIsNotEmpty(oaCUserOffices)){
            List<Long> userIds = new ArrayList<>();
            for (OaCUserOffice oaCUserOffice : oaCUserOffices) {
                userIds.add(oaCUserOffice.getUserId());
            }
            // 用户
            LambdaQueryWrapper<OaCUser> oaCUserQw = Wrappers.<OaCUser>lambdaQuery()
                    .eq(OaCUser::getTag, tag)
                    .in(OaCUser::getUserId, userIds)
                    .orderByDesc(OaCUser::getCreateTime);
            if (CheckUtil.objIsNotEmpty(phone)){
                oaCUserQw.like(OaCUser::getUserPhone, phone);
            }
            if (CheckUtil.objIsNotEmpty(name)){
                oaCUserQw.like(OaCUser::getUserName, name);
            }
            // 用户信息
            Page<OaCUser> oaCUserPage = new Page<>();
            oaCUserPage.setCurrent(current);
            oaCUserPage.setSize(20L);
            IPage<OaCUser> oaCUserIPage = oaCUserMapper.selectPage(oaCUserPage, oaCUserQw);
            List<Map<String, Object>> list = new ArrayList<>();
            // 用户id们
            userIds = new ArrayList<>();
            for (OaCUser oaCUser : oaCUserIPage.getRecords()) {
                Map<String, Object> map = new HashMap<>(16);
                map.put("userId", oaCUser.getUserId().toString());
                map.put("userName", this.isNull(oaCUser.getUserName()));
                map.put("userPhone", this.isNull(oaCUser.getUserPhone()));
                userIds.add(oaCUser.getUserId());
                map.put("personalAmount", "0");
                map.put("officeAmount", "0");
                list.add(map);
            }
            // 钱包
            List<OaCWallet> oaCWallets = oaCWalletMapper.selectList(
                    Wrappers.<OaCWallet>lambdaQuery()
                            .in(OaCWallet::getUserId, userIds)
                            .eq(OaCWallet::getTag, tag)
            );
            // 关联后最终结果
            List<Map<String, Object>> resultPage = new ArrayList<>();
            for (Map<String, Object> map : list) {
                for (OaCWallet oaCWallet : oaCWallets) {
                    if (CheckUtil.objIsNotEmpty(oaCWallet)){
                        if (map.get("userId").equals(oaCWallet.getUserId().toString())){
                            map.put("personalAmount", this.isBigDecimalNull(oaCWallet.getPersonalOfficialBalance()));
                            map.put("officeAmount", this.isBigDecimalNull(oaCWallet.getDeptOfficialBalance()));
                        }
                    }
                }
                resultPage.add(map);
            }
            page.setRecords(resultPage);
            page.setPages(oaCUserIPage.getPages());
            page.setSize(oaCUserIPage.getSize());
            page.setCurrent(current);
            page.setTotal(oaCUserIPage.getTotal());
        }
        result.put("list", page);
        return result;
    }

    /**
     * 部门业务
     * @param tag 租户
     * @param officeId 部门id
     * @param name 查询机构名
     * @param current
     * @param result
     * @return
     */
    private Map<String, Object> officeMap(String tag, Long officeId, String name, Long current, Map<String, Object> result, Long searchOfficeId){
        IPage<Map<String, Object>> page = new Page<>();
        // 部门
        LambdaQueryWrapper<OaSysOffice> oaSysOfficeQw = Wrappers.<OaSysOffice>lambdaQuery()
                .eq(OaSysOffice::getTag, tag)
                .eq(OaSysOffice::getParentId, officeId)
                .eq(OaSysOffice::getType, EOffIceType.dept.getValue())
                .orderByDesc(OaSysOffice::getCreateTime);
        if (CheckUtil.objIsNotEmpty(searchOfficeId)){
            oaSysOfficeQw.eq(OaSysOffice::getOfficeId, searchOfficeId);
        }
        Page<OaSysOffice> oaSysOfficePage = new Page<>();
        oaSysOfficePage.setCurrent(current);
        oaSysOfficePage.setSize(20L);
        IPage<OaSysOffice> oaSysOfficeIPage = oaSysOfficeMapper.selectPage(oaSysOfficePage, oaSysOfficeQw);
        List<Map<String, Object>> list = new ArrayList();
        // 部门id们
        List<Long> officeIds = new ArrayList<>();
        for (OaSysOffice oaSysOffice : oaSysOfficeIPage.getRecords()) {
            Map<String, Object> map = new HashMap<>(16);
            map.put("officeId", oaSysOffice.getOfficeId().toString());
            map.put("officeName", oaSysOffice.getName());
            officeIds.add(oaSysOffice.getOfficeId());
            map.put("personalAmount", "0");
            map.put("officeAmount", "0");
            list.add(map);
        }
        // 关联部门额度
        List<OaSysOfficeAmount> oaSysOfficeAmounts = oaSysOfficeAmountMapper.selectList(Wrappers.<OaSysOfficeAmount>lambdaQuery().in(OaSysOfficeAmount::getOfficeId, officeIds));
        List<Map<String, Object>> resultPage = new ArrayList<>();
        for (Map<String, Object> map : list) {
            for (OaSysOfficeAmount oaSysOfficeAmount : oaSysOfficeAmounts) {
                if (CheckUtil.objIsNotEmpty(oaSysOfficeAmount)){
                    if (map.get("officeId").equals(oaSysOfficeAmount.getOfficeId().toString())){
                        map.put("personalAmount", this.isBigDecimalNull(oaSysOfficeAmount.getPersonalAmount()));
                        map.put("officeAmount", this.isBigDecimalNull(oaSysOfficeAmount.getOfficeAmount()));
                    }
                }
            }
            resultPage.add(map);
        }
        page.setRecords(resultPage);
        page.setPages(oaSysOfficeIPage.getPages());
        page.setSize(oaSysOfficeIPage.getSize());
        page.setCurrent(oaSysOfficeIPage.getCurrent());
        page.setTotal(oaSysOfficeIPage.getTotal());
        result.put("list", page);
        return result;
    }

    /**
     * 插入分配记录表
     * @param officeId 分配机构id
     * @param amount 额度
     * @param amountType 额度类型
     * @param userId 当前用户
     * @param tag 租户
     * @param assignUserid 分配userid
     * @param assignOffice 分配机构id
     * @return
     */
    private void insertOaSysOfficeRecord(Long officeId, BigDecimal amount, Integer amountType, Integer assignType, Long userId, String tag, Long assignUserid, Long assignOffice){
        int i;
        Date date = new Date();
        OaSysOfficeRecord oaSysOfficeRecord = new OaSysOfficeRecord();
        oaSysOfficeRecord.setOfficeRecordId(IDUtil.nextId());
        oaSysOfficeRecord.setOfficeId(officeId);
        oaSysOfficeRecord.setAmount(amount);
        // 分配额度类型
        if (EAmountType.personalAmount.getValue().equals(amountType)){
            oaSysOfficeRecord.setAmountType(EAmountType.personalAmount.getValue());
        } else {
            oaSysOfficeRecord.setAmountType(EAmountType.officeAmount.getValue());
        }
        if (EAssignType.assignPersonal.getValue().equals(assignType)){
            oaSysOfficeRecord.setAssignUserid(assignUserid);
        } else {
            oaSysOfficeRecord.setAssignOffice(assignOffice);
        }
        OaSysUser oaSysUser = oaSysUserMapper.selectById(userId);
        oaSysOfficeRecord.setCreateName(oaSysUser.getName());
        oaSysOfficeRecord.setDistributionType(EDistributionType.assign.getValue());
        oaSysOfficeRecord.setCreateTime(date);
        oaSysOfficeRecord.setUpdateUser(userId);
        oaSysOfficeRecord.setUpdateTime(date);
        oaSysOfficeRecord.setTag(tag);
        oaSysOfficeRecord.setCreateUser(userId);
        i = oaSysOfficeRecordMapper.insert(oaSysOfficeRecord);
        if (i != 1){
            throw PangException.create(EErrorCode.distributionAmountFailure);
        }
    }

    /**
     * 根据分配类型额度类型获取当前部门剩余额度
     * @param amountType 分配额度类型
     * @param oaSysOfficeAmount 机构额度关联实体
     * @param oaSysOffice 机构实体
     * @param size 数量
     * @return
     */
    private BigDecimal getLastAmount(Integer amountType, OaSysOfficeAmount oaSysOfficeAmount, OaSysOffice oaSysOffice, int size, BigDecimal zero, BigDecimal allAmount){
        // 当前部门剩余个人额度
        BigDecimal lastAmount;
        // 分配额度类型
        if (EAmountType.personalAmount.getValue().equals(amountType)){
            lastAmount = oaSysOfficeAmount.getPersonalAmount();
        } else {
            lastAmount = oaSysOfficeAmount.getOfficeAmount();
        }
        lastAmount = lastAmount.subtract(allAmount);
        // 额度不够
        if (lastAmount.subtract(zero).compareTo(zero) < 0){
            throw PangException.create(EErrorCode.deficiencyLimit);
        }
        return lastAmount;
    }

    /**
     * BigDecimal 空处理
     * @param value 数据
     * @return
     */
    private String isBigDecimalNull(Object value){
        return CheckUtil.objIsEmpty(value) ? "0" : value.toString();
    }

    /**
     * 空处理
     * @param value 数据
     * @return
     */
    private String isNull(Object value){
        return CheckUtil.objIsEmpty(value) ? "" : value.toString();
    }
}
